﻿using Microsoft.Extensions.DependencyInjection;
using System.Reflection;

namespace PmSoft.Core.EventBus;

public static class ServiceCollectionExtensions
{
	/// <summary>
	/// 自动注册指定程序集中实现的事件处理器。
	/// </summary>
	/// <param name="services">服务集合，用于注册处理器。</param>
	/// <param name="assembly">要扫描的程序集，不能为 null。</param>
	/// <returns>更新后的服务集合。</returns>
	/// <exception cref="ArgumentNullException">当 <paramref name="services"/> 或 <paramref name="assembly"/> 为 null 时抛出。</exception>
	public static IServiceCollection AddEvents(this IServiceCollection services, Assembly assembly)
	{
		if (services == null) throw new ArgumentNullException(nameof(services));
		if (assembly == null) throw new ArgumentNullException(nameof(assembly));

		var handlerTypes = assembly.GetTypes()
			.Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericTypeDefinition
			&& t.Name.EndsWith("EventHandler"));

		foreach (var type in handlerTypes)
		{
			RegisterEventHandler(services, type, typeof(IEventHandler<>), "Handle");
			RegisterEventHandler(services, type, typeof(IAsyncEventHandler<>), "HandleAsync");
		}

		return services;
	}

	/// <summary>
	/// 注册特定类型的处理器。
	/// </summary>
	/// <param name="services">服务集合。</param>
	/// <param name="type">要检查的类型。</param>
	/// <param name="handlerGenericType">处理器接口的泛型定义类型（如 <see cref="IEventHandler{TEvent}"/> 或 <see cref="IAsyncEventHandler{TEvent}"/>）。</param>
	/// <param name="methodName">处理器方法名（"Handle" 或 "HandleAsync"）。</param>
	private static void RegisterEventHandler(IServiceCollection services, Type type, Type handlerGenericType, string methodName)
	{
		var interfaces = type.GetInterfaces()
			.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == handlerGenericType);

		foreach (var handlerInterface in interfaces)
		{
			var eventType = handlerInterface.GetGenericArguments()[0];
			var method = type.GetMethod(methodName, new[] { eventType });
			if (method != null)
			{
				services.AddScoped(handlerInterface, type);
			}
		}
	}
}
